Add pgrust - #1163
Conversation
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Michael Malis seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
|
Results for Logs:
|
|
Hey - pgrust was specifically designed for graviton. Our JIT compiler only targets the Graviton instruction set. Can you make sure to run it on the c8g.4xl? |
…, c8g.metal-48xl)
|
Results for Logs:
|
|
Results for Logs:
|
|
The run of Logs:
|
|
Very good results, thank you! |
Adds pgrust, a from-scratch rewrite of
PostgreSQL in Rust (AGPL-3.0), wire- and SQL-compatible with PostgreSQL 18.3
(
SELECT version()reportspgrust 0.2 (PostgreSQL 18.3 compatible)).What this entry is (and is not)
hitstable uses pgrust's own columnar storage format (
pgrcolumnar,declared as
USING cbstoreincreate.sql), not the row-oriented heapthe
postgresql*entries use. The entry is taggedcolumn-orientedaccordingly. The engine executes the standard 43 queries through
pgrust's parallel runtime over that columnar store.
bootstrap its own data directory yet:
installuses C PostgreSQL 18'sinitdb(PGDG package, which also providespsql), then runs thepgrust server against that datadir.
Follow-up to #983
The previous attempt to add pgrust (#983, closed) used pgrust v0.1, whose
COPY path falsely rejected valid UTF-8 whenever a multi-byte character
straddled the 64 KiB buffer-refill boundary. The resulting ~690k-statement
split-load workaround could not finish inside the benchmark window and the
automated run produced no results. v0.2 fixes that defect; this entry loads
the dataset as a single
COPYstatement (measured load time: 197 s onc8g.4xlarge) and has been verified end-to-end, unattended, on a fresh
c8g.4xlarge exactly as the automation would run it: clean Ubuntu 24.04
instance, clone,
./benchmark.sh, no manual steps.Data ordering and the load-phase environment (please read)
Two things about the load phase deserve prominence rather than a code
comment:
session sets
PGRUST_COPY_PRESORT=counterid,eventdate,userid,eventtime, watchid, so the server sorts rows into that order while ingesting thesingle
COPY. This is pgrust's mechanism for a clustered primary key —the same
(CounterID, EventDate, UserID, EventTime, WatchID)key theordered entries in this benchmark use (it is the ClickHouse entry's
ORDER BY), expressed as a load-session environment variable becausepgrust has no DDL syntax for it yet. The sort happens inside the timed
load window and is paid for in
load_time.full load-session environment is visible in
loadand is, in short:parallel COPY (DOP 16, stitch pool 8, fill prefetch), parallel parquet
decode (4 GB budget), external-sort memory sizing (512 MB per run,
15 GB in-memory run budget), lz4 for spilled sort runs, and a parallel
ANALYZE sample pool. All of it affects only the measured load. Before
the query sweep the server is restarted with no pgrust-specific
environment: every scored query runs against stock server defaults,
and the concurrent-QPS phase runs against that same stock server.
Setup notes, in the open
installdownloads the official published v0.2 releasebinary for the machine's architecture (sha256-verified). These are
generic-CPU builds for their architecture, with PGO trained on a corpus
disjoint from the 43 queries. The results here are from that published
binary — i.e. what anyone reproduces by running
./benchmark.sh.hits.parquet(format choiceper the README's "select the most optimal dataset format at your
discretion"; duckdb and others also load parquet). One
COPYin onetransaction (
TRUNCATE+COPY ... FREEZE, thenVACUUM ANALYZE).FORMAT 'parquet'/COERCE_EPOCHare pgrust COPY extensions thatdecode the parquet server-side and coerce its epoch-encoded time columns
into the standard TIMESTAMP/DATE schema (the same conversion duckdb's
entry expresses with
epoch_ms()/make_date()).postgresql/install,with two pgrust requirements (
io_method=sync,max_stack_depth=60000per-query tuning:
work_mem = MemTotal/32(pgrust executes analyticalaggregation in
work_mem-bounded hash state, so it is sized as afraction of the machine like every other line of the formula, not fixed
at an OLTP-era 64MB) and
shared_buffers = MemTotal/8(pgrust's columnarscans read through their own arenas and the OS page cache, so a 25%
buffer pool is dead weight; the reclaimed headroom is what lets 10
concurrent connections run the QPS phase safely).
installalsoprovisions the same 16 GB swapfile the benchmark automation's cloud-init
gives every VM (no-op under the automation).
pgrust.condition_cache = on— enabled for parity with ClickHouse,and measured both ways. This is pgrust's equivalent of ClickHouse's
query condition cache: a per-granule cache of filter-condition results
with a 100 MB budget on both sides. ClickHouse ships this default-on
since 25.4 (
use_query_condition_cache = true,src/Core/Settings.cpp:5925, flipped inSettingsChangesHistory.cpp),and the
clickhouseentry here installs a current build — so thepublished ClickHouse rows already run with their condition cache
enabled. pgrust's is off by default in v0.2; enabling it in this entry
puts the two systems on the same footing rather than granting either an
asymmetric advantage. Under ClickBench's caching rules this is a cache
of intermediate filter results at the scan (front of the pipeline),
not a query-result cache. For full transparency we measured both
configurations on identical fresh instances: cache-off hot Σ43 is
13.18 s versus 11.91 s cache-on (the delta concentrated in the
LIKE-heavy URL queries — the same shape ClickHouse's cache targets), and
the entry would score ~4% instead of ~16% ahead of the published
ClickHouse c8g.4xlarge row on the combined metric. If the maintainers
prefer the cache-off configuration for pgrust despite ClickHouse's
default, we will happily switch the entry and results to that arm — both
runs are complete.
query; no
lukewarm-cold-runtag). The concurrent-QPS test is kept(shared daemon, 10 connections).
Results
results/20260730/c8g.4xlarge.json— load_time 197.287 s, data_size17,563,161,388 B, all 43 queries, no nulls (hot Σ43 11.91 s, cold Σ43
121.95 s); concurrent QPS 0.677 with error ratio 0.005. Row count
verified: 99,997,497.
This entry submits c8g.4xlarge only. (pgrust currently has no JIT on
x86-64; an x86 row would not represent the engine and is deliberately not
included.)
Where this lands (against the published c8g.4xlarge rows, official
(t+10ms)geometric-mean scoring): cold runs are strong (well ahead ofthe published ClickHouse row), hot runs slightly behind it, load time
197 s vs 287 s, data size 17.6 GB vs 15.3 GB. On the site's "Combined"
weighting this run reproduces to roughly the mid-teens percent ahead of
the published ClickHouse c8g.4xlarge row (and ~4% ahead with the condition
cache off, as disclosed above) — but per the ClickBench README we present
the numbers, not a scoreboard claim; they will move as neighboring entries
update.
The nonzero concurrent error ratio is real and disclosed: under the
10-connection window, a grouped string-aggregation shape occasionally
errors (
aggregation sink shape violation, ~2 occurrences per 600 swindow; the statement fails cleanly, the server stays up). It is a known
v0.2 defect, tracked on the pgrust side.
🤖 Generated with Claude Code